import { lobby as _ } from './UIConfig';
import { BaseUIRoot } from '../../scripts/libs/ui/BaseUIRoot';
import { _decorator, color, Node, find } from 'cc';
import { lm } from './LobbyManager';
import { FlowStatus } from './Enums';
import { GameKey } from '../../scripts/managers/SubgameConfig';
import { gm } from '../../scripts/managers/GameManager';
import { BindNodeTouch } from '../../scripts/libs/rxjs/cc3/BindNode';
import { EventTouch } from 'cc';
import { Camera } from 'cc';
import { StringTools } from '../../scripts/libs/utils/StringTools';
import { nc } from '../../scripts/libs/rxjs/NotificationCenter';
import { Vec3 } from 'cc';
import { concat, forkJoin, Observable, Subscription } from 'rxjs';
import { ResourceHelper } from './ResourceHelper';
import { FlyCoin } from './game/FlyCoin';
import { v3 } from 'cc';
import { UIOpacity } from 'cc';
import { Timer } from '../../scripts/libs/rxjs/cc3/CreatorSchedule';
import { instantFunc } from '../../scripts/libs/rxjs/cc3/CommonObservable';
import { TweenToStartBSpine } from '../../scripts/libs/rxjs/cc3/TweenStart';
import { am } from '../../scripts/managers/AudioManager';
import { UITransform } from 'cc';
import { screen } from 'cc';
const { ccclass, property } = _decorator;

export namespace lobby {

    function getLobbyPanelKeySet() {
        if (StringTools.getValueInSearch('edit') == '1') {
            return new Set([
                _.PanelKey.EditorStageSelectPanel,
                // _.PanelKey.ResourceFakePanel,
            ]);
        } else {
            return new Set([
                _.PanelKey.LobbyPanel,
                // _.PanelKey.ResourcePanel,
                // _.PanelKey.ResourceFakePanel,
            ]);
        }
    }

    const config = new Map<FlowStatus, Set<_.PanelKey>>([
        [FlowStatus.Empty, new Set()],
        [FlowStatus.Lobby, getLobbyPanelKeySet()],
        [FlowStatus.Game, new Set([
            _.PanelKey.GamePanel,
            // _.PanelKey.ResourceFakePanel,
            // _.PanelKey.ResourcePanel
        ])],
        [FlowStatus.EditorGame, new Set([
            _.PanelKey.EditorGamePanel
        ])]
    ]);

    const gameConfig = new Map<GameKey, Set<_.PanelKey>>([
        [null, new Set()],
        [GameKey.lobby, new Set()],
    ]);

    @ccclass('UIRoot')
    export class UIRoot extends BaseUIRoot {

        get logColorOverride() { return color().fromHEX('#DDDDEE') };

        getPanelKeyEnum() {
            return _.PanelKey as any;
        }

        @property(Node)
        tierFrontNode: Node = null;

        @property(Camera)
        camera: Camera = null;

        willBind() {
            super.willBind();
            lm.uiRoot = this;
        }

        useObserves() {
            return [
                ...super.useObserves(),
                lm.flowStatus.subscribePairWise(pair => {
                    this.statusChangedWithConfig(pair, config);
                }),
                lm.loadingEnabled.subscribeUntilChanged(enabled => enabled ? this.openPanel(_.PanelKey.LoadingPanel as any).subscribe() : this.closePanel(_.PanelKey.LoadingPanel as any).subscribe()),
                gm.curSubgame.subscribePairWise(subgameKey => {
                    this.statusChangedWithConfig(subgameKey, gameConfig);
                }),
                lm.frontTipEnabled.subscribe(enabled => {
                    if (enabled) {
                        this.openPanel(_.PanelKey.FrontTipPanel as any).subscribe(_ => {
                            if (_._ == 'afterOpen') {
                                lm.frontTipReady.value = true;
                            }
                        });
                    } else {
                        this.closePanel(_.PanelKey.FrontTipPanel as any).subscribe()
                    }
                }),
                BindNodeTouch(this.tierFrontNode).subscribe((_: EventTouch) => {
                    _.preventSwallow = true;
                    lm.touchGame.execute(_);
                }),
                nc.subscribe('fly_coins', this.flyCoinHandler.bind(this))
            ];
        }

        onLoadView(): void {
            let transform = this.tierFrontNode.getComponent(UITransform);
            transform.width = screen.windowSize.width;
            transform.height = screen.windowSize.height;
        }

        onDestroyView(): void {
            this._sub_fly_set.forEach(v => v && v.unsubscribe());
        }

        /**
         * 飞金币动画
         */
        _fly_coin_target_worldpos: Vec3 = v3();

        _incNum = 0;
        _sub_fly_set = new Set<Subscription>();
        flyCoinHandler(param: { fromWorldPos: Vec3, count: number, toWorldPos?: Vec3 }) {
            this._incNum++;
            let sub = new Observable(observer => {
                // 分配每一个金币节点包含的真正的金币量
                let { fromWorldPos, count } = param;
                let pairCount = 10;
                if (count < 10) {
                    pairCount = count;
                } else if (count <= 50) {
                    pairCount = 20;
                } else if (count <= 100) {
                    pairCount = 30;
                } else if (count <= 100) {
                    pairCount = 40;
                } else if (count <= 6000) {
                    pairCount = 50;
                } else if (count <= 10000) {
                    pairCount = 60;
                } else if (count <= 25000) {
                    pairCount = 70;
                } else if (count <= 50000) {
                    pairCount = 80;
                } else {
                    pairCount = 90;
                }

                let unitCount = Math.max(Math.floor(count / pairCount), 1);
                let remainCount = count;

                let obs: Observable<any>[] = [];

                let idx = 0;
                while (remainCount > 0) {
                    let curValue = unitCount;
                    if (remainCount < unitCount) {
                        curValue = remainCount;
                    }
                    remainCount -= curValue;

                    let flyCoinNode = ResourceHelper.FlyCoinPool.getNode();
                    let coinFly = flyCoinNode.getComponent(FlyCoin);
                    coinFly.value = curValue;
                    flyCoinNode.setParent(this.tierFrontNode);

                    let p0 = v3();
                    this.tierFrontNode.inverseTransformPoint(p0, fromWorldPos);

                    let p1 = v3(p0);
                    let t = Math.random() * Math.PI * 2;
                    let r = Math.random() * 200 + 100;
                    p1.x += Math.cos(t) * r;
                    p1.y += Math.sin(t) * r;

                    t = Math.random() * Math.PI * 2;
                    r = Math.random() * 40;
                    p0.x += Math.cos(t) * r;
                    p0.y += Math.sin(t) * r;

                    flyCoinNode.setPosition(p0);
                    flyCoinNode.getComponent(UIOpacity).opacity = 0;

                    let p2 = v3();
                    this.tierFrontNode.inverseTransformPoint(p2, this._fly_coin_target_worldpos);

                    if (param.toWorldPos != null) {
                        this.tierFrontNode.inverseTransformPoint(p2, param.toWorldPos);
                    }

                    flyCoinNode.attr({ _orderIdx: idx });
                    let ob = concat(
                        Timer(idx * .01, flyCoinNode),
                        instantFunc(() => {
                            flyCoinNode.getComponent(UIOpacity).opacity = 255;
                        }),
                        TweenToStartBSpine(flyCoinNode, 1, [p0, p1, p2], 3, { easing: 'expoIn' }),
                        instantFunc(() => {
                            ResourceHelper.FlyCoinPool.putNode(flyCoinNode);
                            this.log('@single fly coin value:', coinFly.value)
                            nc.post('fly_coin_inc_value', { value: coinFly.value }); // 在未完成的动画过程中，金币的增长需要及时表现过程中的数值
                            // this.log('@@>>_orderIdx', flyCoinNode['_orderIdx']);

                            // if (flyCoinNode['_orderIdx'] == 0) {
                            //     am.playSfx({ clipName: `ab_lobby/Audio/sfx/gold` });
                            // }
                            // am.playSfx({ clipName: `ab_lobby/Audio/sfx/COINS_Rattle_02_mono` });
                        })
                    );
                    obs.push(ob);

                    idx++;
                }



                gm.coinAnimatingFlags.add('_animating_flag');

                let _sub = forkJoin(obs).subscribe({
                    complete: () => {
                        this.log('@completed!');
                        observer.nextAndComplete(null);
                        gm.coinAnimatingFlags.delete('_animating_flag');
                    }
                })

                return () => {
                    _sub && _sub.unsubscribe();
                    this._sub_fly_set.delete(sub);
                }
            }).subscribe();

            this._sub_fly_set.add(sub);
        }
    }

}